//***************************************************
// ATtiny402 Project
// Morse Message Sender - Japanese Morse Code
// XRQTechLab 2025、08,25 Ver0026
//***************************************************
#include <avr/sleep.h>
#include <avr/interrupt.h>
const int ledPin = 3; // PA0 → 物理ピン5
const int selectPins[] = {0, 1, 2, 4}; // メッセージ選択ピン(物理ピン2,3,4,7)
int dotDuration = 120; // 約20WPM 送出速さ設定
#define NUM_CHANNELS 4
unsigned long lastActivityTime = 0;
bool prevState[NUM_CHANNELS] = {HIGH, HIGH, HIGH, HIGH};
const char* messages[] = {
"# アイウエオ カキクケコ サシスセソ タチツテト ナニヌネノ ハヒフヘホ マミムメモ ヤユヨ ラリルレロ ワヲン *",
"# ガギグゲゴ ザジズゼソ ゙ダジズゼゾ バビブベボ パピプペポ *",
"1234567890 abcdefghijklmnopqrstuvwxyz",
"/ ? - , ( ) + # *" //メッセージ設定 0.1.2.4
};
struct MorseMap {
const char* kana;
const char* code;
};
MorseMap morseTable[] = {
{"ア", "--.--"}, {"イ", ".-"}, {"ウ", "..-"}, {"エ", "-.---"}, {"オ", ".-..."},
{"カ", ".-.."}, {"キ", "-.-.."}, {"ク", "...-"}, {"ケ", "-.--"}, {"コ", "----"},
{"サ", "-.-.-"}, {"シ", "--.-."}, {"ス", "---.-"}, {"セ", ".---."}, {"ソ", "---."},
{"タ", "-."}, {"チ", "..-."}, {"ツ", ".--."}, {"テ", ".-.--"}, {"ト", "..-.."},
{"ナ", ".-."}, {"ニ", "-.-."}, {"ヌ", "...."}, {"ネ", "--.-"}, {"ノ", "..--"},
{"ハ", "-..."}, {"ヒ", "--..-"}, {"フ", "--.."}, {"ヘ", "."}, {"ホ", "-.."},
{"マ", "-..-"}, {"ミ", "..-.-"}, {"ム", "-"}, {"メ", "-...-"}, {"モ", "-..-."},
{"ヤ", ".--"}, {"ユ", "-..--"}, {"ヨ", "--"}, {"ラ", "..."}, {"リ", "--."},
{"ル", "-.--."}, {"レ", "---"}, {"ロ", ".-.-"}, {"ワ", "-.-"}, {"ヲ", ".---"},
{"ン", ".-.-."}, {"゙", ".."}, {"゚",
"..--."}, {" ", ""},
{"/", "-..-."}, {"?", "..--.."}, {",", ".-.-.-"}, {"-", ".--.-"}, {"(", "-.--.-"},
{")", ".-..-."},{"+", ".-.-.."},
{"#", "-..---"}, {"*", "...-."},
{"1", ".----"}, {"2", "..---"}, {"3", "...--"}, {"4", "....-"}, {"5", "....."},
{"6", "-...."}, {"7", "--..."},
{"8", "---.."}, {"9", "----."},
{"0", "-----"},
{"a", ".-"}, {"b", "-..."}, {"c", "-.-."}, {"d", "-.."}, {"e", "."}, {"f", "..-."},
{"g", "--."}, {"h", "...."}, {"i", ".."}, {"j", ".---"}, {"k", "-.-"}, {"l", ".-.."},
{"m", "--"}, {"n", "-."}, {"o", "---"}, {"p", ".--."}, {"q", "--.-"}, {"r", ".-."},
{"s", "..."}, {"t", "-"}, {"u", "..-"}, {"v", "...-"}, {"w", ".--"}, {"x", "-..-"},
{"y", "-.--"}, {"z", "--.."}
};
void setup() {
pinMode(ledPin, OUTPUT);
for (int i = 0; i < NUM_CHANNELS; i++) {
pinMode(selectPins[i], INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(selectPins[i]), wakeUp, FALLING);
}
lastActivityTime = millis();
}
void loop() {
for (int i = 0; i < NUM_CHANNELS; i++) {
bool current = digitalRead(selectPins[i]);
if (prevState[i] == HIGH && current == LOW) {
sendMorseMessage(messages[i]);
lastActivityTime = millis();
delay(1000);
}
prevState[i] = current;
}
if (millis() - lastActivityTime > 180000) { //スリープまでの時間設定
goToSleep();
}
}
void sendMorseMessage(const char* message) {
while (*message) {
if ((unsigned char)*message >= 0xA1) {
char kana[4] = {0};
strncpy(kana, message, 3);
const char* code = getMorseCodeKana(kana);
if (code) sendMorseCode(code);
message += strlen(kana);
} else {
const char* code = getMorseCodeAscii(*message);
if (code) sendMorseCode(code);
message++;
}
}
}
const char* getMorseCodeKana(const char* kana) {
for (int i = 0; i < sizeof(morseTable) / sizeof(MorseMap); i++) {
if (strcmp(morseTable[i].kana, kana) == 0) return morseTable[i].code;
}
return nullptr;
}
const char* getMorseCodeAscii(char c) {
char str[2] = {c, '\0'};
for (int i = 0; i < sizeof(morseTable) / sizeof(MorseMap); i++) {
if (strcmp(morseTable[i].kana, str) == 0) return morseTable[i].code;
}
return nullptr;
}
void sendMorseCode(const char* code) {
while (*code) {
digitalWrite(ledPin, HIGH);
delay(*code == '.' ? dotDuration : dotDuration * 3);
digitalWrite(ledPin, LOW);
delay(dotDuration);
code++;
}
delay(dotDuration * 3);
}
void goToSleep() {
digitalWrite(ledPin, LOW);
sleep_enable();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_cpu();
sleep_disable();
lastActivityTime = millis(); // 復帰後のタイマーリセット
}
void wakeUp() {
// 割り込みでスリープ解除のみ
}